Mikmak Views Refactoren met Partial Views
Probleem
In de Editing en Inserting view is de html en Razor code om de rijen uit de UnitBase tabel te presenteren als een html table precies dezelfde. Straks maken we de Updating en ReadingOne view en mogen we die code nog eens overtypen. Ten eerste vind ik het vervelend nog eens dezelfde code te typen of te kopiëren en ten tweede is het lastig om nog iets in die code te wijzigen. Want dan moet je de wijzigingen op vier plaatsen gaan aanbrengen. Er bestaat hiervoor een acroniem DRY dat staat voor don't repeat yourself.
We hebben al geleerd hoe je html en Razor code die op alle pagina's staat beter in een Lay-out pagina steekt. Maar de lijst met UnitBase rijen moet niet op alle pagina's getoond worden, enkel op de CRUD pagina's voor de UnitBase entiteit.
Het MVC framework heeft hiervoor een elegante oplossing, namelijk partial views. En hoe je dat gebruikt, leren we in deze les.
Design
- We leren eerst hoe je partial views gebruikt in ASP.NET MVC:
- We passen deze kennis toe op onze webwinkel:
- een partial view voor UnitBase ReadingAll
- de partial view oproepen vanuit de CRUD views
- de UnitBaseController klasse aanpassen
- testen
- oefening: refactoring
Oplossing
- Maak een partial view in de map /Views/UnitBase met de naam ReadingAll.cshtml. Voeg bovenaan het
@model
directive toe om te verwijzen naar een collectie van de rijen van de UnitBase tabel. Door het model toe te voegen aan de partial view is deze partial view 'onafhankelijk' van de bovenliggende view.@model IEnumerable<Webwinkel.Models.UnitBase> <div class="list"> <!-- kijk eerst na als er objecten in het model staan --> @if (Model.Any()) { <table> @foreach (var item in Model) { <tr> <td> <a href="/UnitBase/ReadingOne/@item.Id" class="tile"> <span class="icon-arrow-right"></span> <span class="screen-reader-text">Select</span> </a> </td> <td> @item.Code </td> <td> @item.Name </td> </tr> } </table> } else { <p>Geen basiseenheden ingevoerd in de UnitBase entiteit.</p> } </div>
- De partial view ReadingAll.cshtml oproepen vanuit de bovenliggende CRUD views en het
@model
directive verwijderen. Het model voor de lijst wordt immers niet hier meer doorgegeven maar in de partial view. Als voorbeeld wijzigen we de Views/UnitBase/Editing.cshtml:@*model IEnumerable<Webwinkel.Models.UnitBase> <--- verwijder @model directive, ik heb het in commentaar gezet *@ @{ Layout = "~/Views/Shared/MasterLayout.cshtml"; } <div class="floor" id="flat-entity-floor"> <div class="control-panel"> <a href="/Home/Index" class="tile"> <span class="icon-menu2"></span> <span class="screen-reader-text">Home</span> </a> <h1>MikMak</h1> </div> <form class="showroom" action="/UnitBase" method="post"> <header> <h2>Basiseenheid</h2> <div id="command-panel" class="command-panel"> <a href="/UnitBase/Inserting" class="tile"> <span class="icon-plus"></span> <span class="screen-reader-text">Inserting</span> </a> </div> </header> @Html.Action("ReadingAll") </form> </div>
- De
ReadingAll
actiemethode toevoegen in deUnitBaseController
klasse. De actiemethode maakt een instantie van de DbContext/Dal en geeft een verwijzing naar de DbSet collectie van UnitBase tabel door. De naam van de partial view die ingevoegd moet worden in de bovenliggende view hoeven we niet mee te geven omdat we de notatieafspraken van ASP.NET MVC volgen en dezelfde naam voor de actiemethode en de partial view gebruiken.public ActionResult ReadingAll() { Models.Dal dal = new Models.Dal(); return PartialView(dal.DbSetUnitBase); }
We kuisen de actiemethode Editing op. Daar moeten we het model niet meer instantiëren. We kunnen die code dus schrappen:public ActionResult Editing() { // Models.Dal dal = new Models.Dal(); <--- te verwijderen return View(/*dal.DbSetUnitBase <--- te verwijderen */); }
- De werking van de software is niet veranderd, maar we hebben wel de complexiteit ervan verkleind door repeterende code af te zonderen, te verzelfstandigen in een partial view:
Mikmak Refactoring View UnitBase Editing - Doe hetzelfde voor
Inserting.cshtml
pagina en deInserting
enInsert
actiemethode in deUnitBaseController
.